package com.chenwc;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.obs.services.model.*;
import org.junit.jupiter.api.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import shade.okhttp3.*;

import javax.activation.MimetypesFileTypeMap;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * @author chenwc
 * @package com.chenwc
 * @project ObjectStorage
 * @date 2024/4/23
 */
public class ObsTest {
    private static final Logger logger = LoggerFactory.getLogger(ObsTest.class);

    /**
     * 在测试类执行之前执行的方法 必须用static
     */
    @BeforeAll
    public static void beforeAll() {
        ObsUtil.setObsClient("",
                "",
                "https://obs.cn-south-1.myhuaweicloud.com");
    }

    /**
     * 在每个测试用例后执行的方法 必须用static声明
     */
    @AfterAll
    public static void afterAll() {
        ObsUtil.close();
    }


    @Test
    @Tag("HuaweiObs")
    @DisplayName("listBucket")
    void listBucket() {
        List<ObsBucket> buckets = ObsUtil.listBucket();
        buckets.forEach(bucket -> {
            logger.info("bucketName: {}", bucket.getBucketName());
            logger.info("bucketLocation: {}", bucket.getLocation());
        });

    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("getBucketMetadata")
    void getBucketMetadata() {
        BucketMetadataInfoResult result = ObsUtil.getBucketMetadata("calvinchan");
        logger.info("BucketMetadataInfoResult: {}", JSON.toJSONString(result, JSONWriter.Feature.WriteMapNullValue));
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("getBucketAcl")
    void getBucketAcl() {
        AccessControlList acl = ObsUtil.getBucketAcl("calvinchan");
        logger.info("AccessControlList: {}", JSON.toJSONString(acl, JSONWriter.Feature.WriteMapNullValue));
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("setBucketAcl")
    void setBucketAcl() {
        String exampleBucket = "calvinchan";
        // 示例桶策略
        String examplePolicy =
                "{\"Statement\":[{\"Principal\":\"*\",\"Effect\":\"Allow\",\"Action\":\"ListBucket\",\"Resource\":\""
                        + exampleBucket
                        + "\"}]}";
        ObsUtil.setBucketPolicy(exampleBucket, examplePolicy);
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("putObjectByObjectMetadata")
    void putObjectByObjectMetadata() throws IOException, NoSuchAlgorithmException {
        String exampleBucket = "calvinchan";
        File exampleFile = new File("D:\\Downloads\\elasticsearch-analysis-ik-7.17.5.zip");
        ObjectMetadata metadata = new ObjectMetadata();
        // 设置文件大小
        metadata.setContentLength(exampleFile.length());

        String contentType = new MimetypesFileTypeMap().getContentType(exampleFile);
        if (contentType == null || contentType.isEmpty()) {
            contentType = "application/octet-stream";
        }
        // 设置文件类型
        metadata.setContentType(contentType);

        String base64Md5 = ObsUtil.getObsClient().base64Md5(Files.newInputStream(Paths.get(exampleFile.getAbsolutePath())));
        // 设置文件MD5
        metadata.setContentMd5(base64Md5);

        // 设置文件下载名称
        metadata.setContentDisposition("attachment;filename=" + exampleFile.getName());

        Map<String, Object> userMetadata = new HashMap<>();
        userMetadata.put("user-defined-key", "user-defined-value");
        metadata.setUserMetadata(userMetadata);

        // 设置对象存储类别为低频访问存储
        metadata.setObjectStorageClass(StorageClassEnum.WARM);

        ObsUtil.putObjectByObjectMetadata(exampleBucket, exampleFile.getName(), exampleFile, metadata);
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("multipartUploadObject")
    void multipartUploadObject() {
        File exampleFile = new File("D:\\Downloads\\s3-api.pdf");
        ObsUtil.multipartUploadObject("calvinchan", exampleFile.getName(), exampleFile);
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("getPostObjectFormData")
    void getPostObjectFormData() {
        File localFile = new File("D:\\Downloads\\aws-sdk-java-dg-v2.pdf");
        String bucketName = "calvinchan";
        String key = localFile.getName();

        Map<String, Object> formData = ObsUtil.getPostObjectFormData(localFile);
        logger.info("resp: {}", JSON.toJSONString(formData, JSONWriter.Feature.WriteMapNullValue));

        // Upload an image using POST object with form-data.
        MultipartBody.Builder multipartBuilder = new MultipartBody.Builder();
        multipartBuilder.setType(MultipartBody.FORM);
        for (Map.Entry<String, Object> entry : formData.entrySet()) {
            multipartBuilder.addFormDataPart(entry.getKey(), (String) entry.getValue());
        }

        multipartBuilder.addFormDataPart("key", key);
        multipartBuilder.addFormDataPart("Content-Type", "multipart/form-data");

        String contentType = new MimetypesFileTypeMap().getContentType(localFile);
        if (contentType == null || contentType.isEmpty()) {
            contentType = "application/octet-stream";
        }
        // "file" 必须最后添加
        multipartBuilder.addFormDataPart(
                "file", localFile.getName(), RequestBody.create(localFile, MediaType.parse(contentType)));

        Request request =
                new Request.Builder()
                        .url("https://" + bucketName + ".obs.cn-south-1.myhuaweicloud.com")
                        .post(multipartBuilder.build())
                        .build();
        OkHttpClient httpClient = new OkHttpClient().newBuilder().build();
        try (Response response = httpClient.newCall(request).execute()) {
            if (response.body() != null) {
                logger.info("response: {}", new String(Objects.requireNonNull(response.body()).bytes(), StandardCharsets.UTF_8));
            }
            if (response.isSuccessful()) {
                logger.info(localFile.getName() + " 使用 POST 成功上传！");
            } else {
                logger.info("上传失败 " + localFile.getName());
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("downloadObjectProgressImages")
    void downloadObjectProgressImages() {
        String bucketName = "calvinchan";
        String key = "微信图片_20221126230842.jpg";
        String outputFilePath = "D:\\Downloads\\" + System.currentTimeMillis() + ".jpg";
        String imageProcess = "image/resize,m_fixed,w_100,h_100/rotate,90";
        ObsUtil.downloadObjectProgressImages(bucketName, key, outputFilePath, imageProcess);
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("listAllObjectsByPage")
    void listAllObjectsByPage() {
        String bucketName = "calvinchan";
        String prefix = "";
        List<ObsObject> obsObjects = ObsUtil.listAllObjectsByPage(bucketName, prefix);
        obsObjects.forEach(obsObject -> {
            logger.info("key: {}", obsObject.getObjectKey());
        });
    }

    @Test
    @Tag("HuaweiObs")
    @DisplayName("getObjectTemporarySignatureUrl")
    void getObjectTemporarySignatureUrl() {
        String bucketName = "calvinchan";
        String key = "微信图片_20221126230842.jpg";
        logger.info("url: {}", ObsUtil.getObjectTemporarySignatureUrl(bucketName, key, 60));
    }
}
